using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;

namespace Shrapnel
{
	public partial class View
	{
		/// <summary>
		/// Most recent position (in world coordinates) from where we are moving
		/// </summary>
		private PointF movingMostRecentPositionWorld;

		/// <summary>
		/// Cached list of all cables that need to be updated due to the movement of several nodes
		/// </summary>
		private List<Cable> movingAffectedCables = new List<Cable>();



		private void OnMovingStart(Point mousePosition)
		{
			// Determine which node we clicked
			PointF positionWorld = viewState.ScreenToWorld(new PointF(mousePosition.X, mousePosition.Y));
			BoundingBox selectionBox = new BoundingBox(positionWorld, new SizeF(1, 1));
			EnforceMinimumBoxSize(ref selectionBox);
			List<Element> clickedItems = GetOverlappingElements(selectionBox, true);

			// See if everything we clicked was already in our selection
			bool partOfOurSelection = true;

			foreach (Element element in clickedItems)
			{
				if (element is Node)
				{
					if (!selection.Contains(element))
					{
						partOfOurSelection = false;
						break;
					}
				}
			}

			// If we clicked on something that was not selected, we reset our selection to the stuff we just clicked
			if (!partOfOurSelection)
			{
				selection.Clear();
				foreach (Element element in clickedItems)
				{
					if (element is Node)
					{
						selection.Add(element);
					}
				}

				Invalidate();
			}

			// Find all cables that are attached to any of the currently selected nodes
			movingAffectedCables = GetCablesAttachedToSelection();

			movingMostRecentPositionWorld = positionWorld;
		}

		private void OnMovingStop(Point mousePosition)
		{
			automaticPanner.Stop();

			Invalidate();
		}

		private void OnMovingTick(Point mousePosition)
		{
			PointF positionWorld = viewState.ScreenToWorld(new PointF(mousePosition.X, mousePosition.Y));
			PointF moveDelta = new PointF(
				positionWorld.X - movingMostRecentPositionWorld.X,
				positionWorld.Y - movingMostRecentPositionWorld.Y);

			movingMostRecentPositionWorld = positionWorld;

			// Move all nodes
			foreach (Element element in selection)
			{
				if (element is Node)
				{
					element.Position = new PointF(
						element.Position.X + moveDelta.X,
						element.Position.Y + moveDelta.Y);
				} 
			}

			// Update all cables' areas, since our nodes were moved
			foreach (Element element in selection)
			{
				if (element is Cable)
				{
					((Cable)element).RecalculateOccupiedArea();
				}
			}

			foreach (Cable cable in movingAffectedCables)
			{
				cable.RecalculateOccupiedArea();
			}

			UpdateAutomaticPanning(mousePosition);

			Invalidate();
		}
	}
}
